package ai.text.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import ai.graph.GraphConstants;

import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.Vertex;
import edu.uci.ics.jung.graph.impl.DirectedSparseEdge;
import edu.uci.ics.jung.graph.impl.DirectedSparseGraph;
import edu.uci.ics.jung.graph.impl.DirectedSparseVertex;
import edu.uci.ics.jung.utils.UserData;
import edu.uci.ics.jung.utils.UserDataContainer.CopyAction;

import opennlp.tools.lang.english.SentenceDetector;
import opennlp.tools.lang.english.Tokenizer;
import opennlp.tools.lang.english.TreebankParser;
import opennlp.tools.parser.Parse;
import opennlp.tools.parser.ParserME;
import opennlp.tools.sentdetect.SentenceDetectorME;
import opennlp.tools.util.Span;

public class OpenNLPAdapter {
	
	public static final String MODEL_PATH = "N:/java/_libs/opennlp-tools-1.3.0/models/";
	SentenceDetectorME sdetector;
	Tokenizer tokenizer;
	ParserME parser;
	
	
	public OpenNLPAdapter() {
		super();
		try {
			sdetector =
			    new SentenceDetector(MODEL_PATH+"sentdetect/EnglishSD.bin.gz");
			tokenizer = new Tokenizer(MODEL_PATH+"tokenize/EnglishTok.bin.gz");
			
			boolean useTagDict = true;
			boolean useCaseInsensitiveTagDict = false;
			int beamSize = ParserME.defaultBeamSize;
			double advancePercentage = ParserME.defaultAdvancePercentage;
			parser = TreebankParser.getParser(
					MODEL_PATH+"parser/", useTagDict, useCaseInsensitiveTagDict,
			        beamSize, advancePercentage);
		} catch (IOException e) {
			throw new IllegalArgumentException(e);
		}
	}
	
	public String[] getSentenses(String str) {	 
//		 break a paragraph into sentences
		return sdetector.sentDetect(str);
		
	}
	
	public Parse getFullParseTree(String sentense) {
		
			String[] tokens = tokenizer.tokenize(sentense);
			 
//			 build a string to parse as well as a list of tokens
			StringBuffer sb = new StringBuffer();
			List<String> tokenList = new ArrayList<String>();
			for (int j = 0; j < tokens.length; j++)
			{
			    String tok =tokens[j]; //convertToken(tokens[j]);
			    tokenList.add(tok);
			    sb.append(tok).append(" ");
			}
			String text = sb.substring(0, sb.length() - 1).toString();
		
			
			
			// the parent parse instance spans the entire sentence
			Parse p = new Parse(text, new Span(0, text.length()), "INC", 1, null);

			// create a parse object for each token and add it to the parent
			int start = 0;
			for (Iterator ti = tokenList.iterator(); ti.hasNext();) {
				String tok = (String) ti.next();
				p.insert(new Parse(text, new Span(start, start + tok.length()),
						ParserME.TOK_NODE, 0));
				start += tok.length() + 1;
			}
			
			// fetch multiple possible parse trees
			Parse[] parses = parser.parse(p, 3); //numParses
			return parses[0];
	}
	
	
	public static void buildXML(Parse pp, StringBuffer sb) {

			    int start;
			    start = pp.getSpan().getStart();
			    if (!pp.getType().equals(ParserME.TOK_NODE)) {
			      sb.append("<"+pp.getType()+">");
	
			    }
			    for (Parse c : pp.getChildren()) {
			      Span s = c.getSpan();
			      if (start < s.getStart()) {
			        //System.out.println("pre "+start+" "+s.getStart());
			        sb.append(pp.getText().substring(start, s.getStart()));
			      }
			      buildXML(c ,sb);
			      start = s.getEnd();
			    }
			    sb.append(pp.getText().substring(start, pp.getSpan().getEnd()));
			    if (!pp.getType().equals(ParserME.TOK_NODE)) {
			    	 sb.append("</"+pp.getType()+">");
			    }
			
	}

	public Graph buildGraph(Parse fullParseTree) {
		Graph g = new DirectedSparseGraph();
		return buildGraph(fullParseTree, g, null);
	}
	
	public Graph buildGraph(Parse pp, Graph g, Vertex parent) {
		if(pp.getType().length() == 0) {
			return g;
		}
		Vertex current = g.addVertex(new DirectedSparseVertex());
		if(parent != null) {
			g.addEdge(new DirectedSparseEdge(parent, current));
		}

	    int start;
	    start = pp.getSpan().getStart();
	    if (!pp.getType().equals(ParserME.TOK_NODE)) {
	      current.setUserDatum(GraphConstants.TYPE, pp.getType(),UserData.SHARED);
	    }
	    StringBuffer sb = new StringBuffer();
	    for (Parse c : pp.getChildren()) {
	      Span s = c.getSpan();
	      if (start < s.getStart()) {
	        //System.out.println("pre "+start+" "+s.getStart());
	       // sb.append(pp.getText().substring(start, s.getStart()));
	      }
	      buildGraph(c ,g, current);
	      start = s.getEnd();
	    }
	    Span s = pp.getSpan();
	    //sb.append(pp.getText().substring(start, pp.getSpan().getEnd()));
	    sb.append(pp.getText().substring(s.getStart(), s.getEnd()));
	    current.setUserDatum(GraphConstants.NAME, 
	    		sb.toString()
	    		, UserData.SHARED);
		return g;
	}
	
	public class BuildGraphVisitor implements ParseTreeVisitor{
		
		Graph g = new DirectedSparseGraph();
		Vertex parent;
		Vertex current;
		
		public void begin(String type, String value) {
			Vertex current = g.addVertex(new DirectedSparseVertex());
			if(parent != null) {
				g.addEdge(new DirectedSparseEdge(parent, current));
			}
		}
		
		public void end(String type, String value) {
			
		}
	}
	
	public interface ParseTreeVisitor {
		public void begin(String type, String value);
		public void end(String type, String value);
	}
}
